package cn.iocoder.yudao.module.digital.service.cardchannel.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import cn.iocoder.yudao.module.digital.dal.dataobject.cardkeyorder.CardkeyOrderCardSecretDO;
import cn.iocoder.yudao.module.digital.dal.dataobject.cardkeyorder.CardkeyOrderDO;
import cn.iocoder.yudao.module.digital.enums.cardkeysecret.CardKeySourceEnum;
import cn.iocoder.yudao.module.digital.service.cardchannel.ICardChannel;
import cn.iocoder.yudao.module.digital.service.cardchannel.ICardChannelManager;
import cn.iocoder.yudao.module.digital.service.cardchannel.impl.bamboo.CardChannelBambooImpl;
import cn.iocoder.yudao.module.digital.service.cardchannel.impl.bh.CardChannelBHImpl;
import cn.iocoder.yudao.module.digital.service.cardchannel.model.common.*;
import cn.iocoder.yudao.module.digital.service.cardkeyorder.CardkeyOrderService;
import cn.iocoder.yudao.module.digital.util.CardKeyUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Slf4j
public class CardChannelManagerImpl implements ICardChannelManager {
    @Resource
    private CardChannelBHImpl bhImpl;
    @Resource
    private CardChannelBambooImpl bambooImpl;
    @Resource
    private CardkeyOrderService cardkeyOrderService;

    @Override
    public ICardChannel getChannelImpl(CardKeySourceEnum source) {
        switch (source) {
            case BAMBOO_API:
                return bambooImpl;
            case BLACK_HAWK_API:
                return bhImpl;
            default:
                throw new IllegalArgumentException(String.format("source不支持 [%s]", source));
        }
    }

    @Override
    public List<CdkProduct> getAllProducts(CardKeySourceEnum source) {
        return getChannelImpl(source).getAllProducts();
    }

    @Override
    public CdkGenCardResult onlyQueryOrderResult(CardkeyOrderDO cardKeyOrder) {
        final String cardOrderId = cardKeyOrder.getId();
        CdkGenCardResult res = null;
        final CdkOrderStatusEnum oldOrderStatus = CdkOrderStatusEnum.fromValue(cardKeyOrder.getOrderStatus());
        if (oldOrderStatus.isNotCreateCardCompletedStatus() && StrUtil.isNotEmpty(cardKeyOrder.getChannelOrderId())) {
            // 还没有出最终结果，去渠道查询订单
            final CardKeySourceEnum source = CardKeySourceEnum.fromValue(cardKeyOrder.getSource());
            res = getChannelImpl(source).queryOrder(cardOrderId, cardKeyOrder.getChannelOrderId());
            res.setCreateDuration(Duration.between(cardKeyOrder.getCreateTime(), LocalDateTime.now()));
            log.info("去渠道查询卡密订单, cardOrderId = {}, channelOrderId = {}, oldOrderStatus = {}, res = {}",
                    cardOrderId, cardKeyOrder.getChannelOrderId(), oldOrderStatus, JsonUtils.toJsonString(res));
        } else {
            log.warn("已经有最终结果, cardOrderId = {}, channelOrderId = {}, oldOrderStatus = {}",
                    cardOrderId, cardKeyOrder.getChannelOrderId(), oldOrderStatus);
        }

        return res;
    }

    @Override
    public CdkGenCardResult queryOrderResult(String cardOrderId) {
        // 查询订单是否存在
        final CardkeyOrderDO cardKeyOrder = cardkeyOrderService.getCardKeyOrderNoCheck(cardOrderId);
        if (cardKeyOrder == null) {
            log.info("查询卡密订单-为空, cardOrderId = {}", cardOrderId);
            return null;
        }

        final CdkGenCardResult res;
        final CdkOrderStatusEnum oldOrderStatus = CdkOrderStatusEnum.fromValue(cardKeyOrder.getOrderStatus());
        if (oldOrderStatus.isNotCreateCardCompletedStatus() && StrUtil.isNotEmpty(cardKeyOrder.getChannelOrderId())) {
            // 还没有出最终结果，去渠道查询订单
            final CardKeySourceEnum source = CardKeySourceEnum.fromValue(cardKeyOrder.getSource());
            res = getChannelImpl(source).queryOrder(cardOrderId, cardKeyOrder.getChannelOrderId());
            res.setCreateDuration(Duration.between(cardKeyOrder.getCreateTime(), LocalDateTime.now()));
            log.info("去渠道查询卡密订单, cardOrderId = {}, channelOrderId = {}, res = {}",
                    cardOrderId, cardKeyOrder.getChannelOrderId(), JsonUtils.toJsonString(res));

            // 更新卡密订单
            updateCardKeyOrder(cardKeyOrder, res);
        } else {
            // 已经有最终结果，去数据库查询订单
            res = new CdkGenCardResult();
            res.setOrderStatus(oldOrderStatus);
            res.setErrorMsg(cardKeyOrder.getErrorMsg());
            res.setCreateDuration(Duration.between(cardKeyOrder.getCreateTime(), LocalDateTime.now()));
            if (CollUtil.isNotEmpty(cardKeyOrder.getCards())) {
                final List<CdkCardSecret> cards = cardKeyOrder.getCards().stream().map(v -> CardKeyUtils.toCdkSecret(v)).collect(Collectors.toList());
                res.setCards(cards);
            }

            log.info("去数据库查询卡密订单, cardOrderId = {}, channelOrderId = {}, res = {}",
                    cardOrderId, cardKeyOrder.getChannelOrderId(), JsonUtils.toJsonString(res));
        }

        return res;
    }

    // 更新卡密订单
    @Override
    public void updateCardKeyOrder(CardkeyOrderDO cardKeyOrder, CdkGenCardResult res) {
        final String cardOrderId = cardKeyOrder.getId();
        final CdkOrderStatusEnum oldOrderStatus = CdkOrderStatusEnum.fromValue(cardKeyOrder.getOrderStatus());
        if (oldOrderStatus.isNotCreateCardCompletedStatus()) {
            // 旧订单状态为未完成
            final List<CardkeyOrderCardSecretDO> cards = new ArrayList<>();
            if (CollUtil.isNotEmpty(res.getCards())) {
                res.getCards().forEach(v -> {
                    final CardkeyOrderCardSecretDO card = CardKeyUtils.toCardkeyOrderCardDO(v);
                    cards.add(card);
                });
            }

            cardkeyOrderService.updateCardKeyOrder(cardOrderId, res.getChannelCardOrderId(), res.getChannelInnerOrderId(), res.getOrderStatus(), res.getErrorMsg(), cards);
            log.info("更新卡密订单, cardOrderId = {}, channelOrderId = {}, orderStatus = {}, errorMsg = {}, cards = {}",
                    cardOrderId, res.getChannelCardOrderId(), res.getOrderStatus(), res.getErrorMsg(), JsonUtils.toJsonString(cards));
        } else {
            cardkeyOrderService.updateCardKeyOrderFailOrException(cardOrderId, res.getChannelCardOrderId(), res.getChannelInnerOrderId(), res.getOrderStatus(), res.getErrorMsg());
            log.warn("更新卡密订单, cardOrderId = {}, channelOrderId = {}, orderStatus = {}, errorMsg = {}",
                    cardOrderId, res.getChannelCardOrderId(), res.getOrderStatus(), res.getErrorMsg());
        }
    }

    @Override
    public CdkGenCardResult createMultipleQuantitiesOrder(CardKeySourceEnum source, CdkGenCardReq req) {
        log.info("创建单商品多数量订单, source = {}, req = {}", source, JsonUtils.toJsonString(req));

        final String cardOrderId = cardkeyOrderService.createCardKeyOrder(source, req.getCardOrderId(), req.getProducts());
        log.info("存储单商品多数量订单, cardOrderId = {}", cardOrderId);

        // 调用渠道创建订单
        final CdkGenCardResult res = getChannelImpl(source).createMultipleQuantitiesOrder(req);

        // 查询卡密订单
        final CardkeyOrderDO cardKeyOrder = cardkeyOrderService.getCardKeyOrderNoCheck(cardOrderId);

        // 更新卡密订单
        updateCardKeyOrder(cardKeyOrder, res);

        return res;
    }

    // 创建单商品单数量订单
    @Override
    public CdkGenCardResult createSingleQuantitiesOrder(CardKeySourceEnum source, CdkGenCardReq req) {
        log.info("创建单商品单数量订单, source = {}, req = {}", source, JsonUtils.toJsonString(req));
        Assert.isTrue(req.getProducts().size() == 1);
        final CdkGenCardReq.Product product = req.getProducts().get(0);
        Assert.isTrue(product.getQuantity() == 1);

        final String cardOrderId = cardkeyOrderService.createCardKeyOrder(source, req.getCardOrderId(), req.getProducts());
        log.info("存储单商品单数量订单, cardOrderId = {}", cardOrderId);

        // 调用渠道创建订单
        final CdkGenCardResult res = getChannelImpl(source).createSingleQuantitiesOrder(req);

        // 查询卡密订单
        final CardkeyOrderDO cardKeyOrder = cardkeyOrderService.getCardKeyOrderNoCheck(cardOrderId);

        // 更新卡密订单
        updateCardKeyOrder(cardKeyOrder, res);

        return res;
    }

    // 创建卡密聚合订单
    @Override
    public CdkGenCardResult createAggregatedOrder(CardKeySourceEnum source, CdkGenCardReq req) {
        log.info("创建卡密聚合订单, source = {}, req = {}", source, JsonUtils.toJsonString(req));

        final String cardOrderId = cardkeyOrderService.createCardKeyOrder(source, req.getCardOrderId(), req.getProducts());
        log.info("存储卡密聚合订单, cardOrderId = {}", cardOrderId);

        // 调用渠道创建订单
        final CdkGenCardResult res = getChannelImpl(source).createAggregatedOrder(req);

        // 查询卡密订单
        final CardkeyOrderDO cardKeyOrder = cardkeyOrderService.getCardKeyOrderNoCheck(cardOrderId);

        // 更新卡密订单
        updateCardKeyOrder(cardKeyOrder, res);

        return res;
    }

    public static void main(String[] args) {
        final Duration createDuration = Duration.between(LocalDateTime.now().minusMinutes(130), LocalDateTime.now());
        System.out.println(createDuration);
    }

}
